package middleware

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/hex"
	"github.com/gin-gonic/gin"
	"inspector/internal/config"
	"inspector/pkg/code"
	"inspector/pkg/errors"
	"inspector/pkg/log"
	"io"
)

var webhookSecrets = []byte(config.Get().GetAtomConfig().WebhookSecrets)

func WebhookCheck() gin.HandlerFunc {
	return func(c *gin.Context) {

		payload, err := io.ReadAll(c.Request.Body)
		if err != nil {
			// todo log
			c.Error(errors.New(code.NewErrBadRequest(), "Invalid request body"))
			c.Abort()
			return
		}

		signatureSHA1 := c.GetHeader("X-Hub-Signature")
		signatureSHA256 := c.GetHeader("X-Hub-Signature-256")

		if verifySignatureSHA1(webhookSecrets, payload, signatureSHA1) {
		} else if verifySignatureSHA256(webhookSecrets, payload, signatureSHA256) {
		} else {
			// todo log
			//c.Error(errors.New(code.NewErrInvalidAuthHeader(), "Invalid signature"))
			//c.Abort()
			//return
			log.Info("verity failed.")
		}
		// todo log
		c.Request.Body = io.NopCloser(bytes.NewBuffer(payload))
		c.Next()
	}
}

// verifySignatureSHA1 checks SHA1 signature
func verifySignatureSHA1(secret, payload []byte, signature string) bool {
	mac := hmac.New(sha1.New, secret)
	mac.Write(payload)
	expectedMAC := mac.Sum(nil)
	expectedSignature := "sha1=" + hex.EncodeToString(expectedMAC)
	return hmac.Equal([]byte(expectedSignature), []byte(signature))
}

// verifySignatureSHA256 checks SHA256 signature
func verifySignatureSHA256(secret, payload []byte, signature string) bool {
	mac := hmac.New(sha256.New, secret)
	mac.Write(payload)
	expectedMAC := mac.Sum(nil)
	expectedSignature := "sha256=" + hex.EncodeToString(expectedMAC)
	return hmac.Equal([]byte(expectedSignature), []byte(signature))
}
